#ifndef _MPxTransformationMatrix
#define _MPxTransformationMatrix
//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc., and/or its licensors.  All
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related
// material (collectively the "Data") in these files contain unpublished
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its
// licensors,  which is protected by U.S. and Canadian federal copyright law
// and by international treaties.
//
// The Data may not be disclosed or distributed to third parties or be
// copied or duplicated, in whole or in part, without the prior written
// consent of Autodesk.
//
// The copyright notices in the Software and this entire statement,
// including the above license grant, this restriction and the following
// disclaimer, must be included in all copies of the Software, in whole
// or in part, and all derivative works of the Software, unless such copies
// or derivative works are solely in the form of machine-executable object
// code generated by a source language processor.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE,
// OR ARISING FROM A COURSE OF DEALING, USAGE, OR TRADE PRACTICE. IN NO
// EVENT WILL AUTODESK AND/OR ITS LICENSORS BE LIABLE FOR ANY LOST
// REVENUES, DATA, OR PROFITS, OR SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK AND/OR ITS LICENSORS HAS
// BEEN ADVISED OF THE POSSIBILITY OR PROBABILITY OF SUCH DAMAGES.
// ==========================================================================
//+
//
// CLASS:	MPxTransformationMatrix
//
// Description:
//
//		This is the API side of user defined transformation matrices.
//		Any MPxTransformationMatrix will have an associated THxformMatrix
//		class to handle the Maya side of things.
//
// ****************************************************************************

#if defined __cplusplus

// ****************************************************************************
// INCLUDED HEADER FILES

#include <maya/MTypeId.h>
#include <maya/MStatus.h>
#include <maya/MTypes.h>
#include <maya/MTransformationMatrix.h>

#include <maya/MMatrix.h>
#include <maya/MQuaternion.h>
#include <maya/MEulerRotation.h>
#include <maya/MVector.h>
#include <maya/MPoint.h>

// ****************************************************************************
// CLASS DECLARATION (MPxTransformationMatrix)

//! \ingroup OpenMaya MPx
//! \brief Base class of all user defined transformation matrices. 
/*!
	MPxTransformationMatrix is the parent class for all user defined
	transformation matrices. A transformation matrix is a class that
	holds the individual components (i.e. translate, rotate, scale, pivots,
	etc.) that are used to construct a 4x4 matrix. Given that different
	combinations of transform components may produce similar 4x4 matrices,
	it is not always possible to get a generic 4x4 matrix and decompose it
	into unique components. This class allows better control over which
	components are changed than a generic 4x4 MMatrix could offer.

	The MPxTransformationMatrix class is designed for use as the
	mathematical brains behind the MPxTransform node. This separation is
	useful for class reuse (different types of MPxTransform nodes may still
	use the same MPxTransformationMatrix class) as well as simplifying the
	MPxTransform class.

	The MPxTransformationMatrix class is registered using the
	MFnPlugin::registerTransform() method. Both the MPxTransform and the
	MPxTransformationMatrix classes are registered in the same method. This
	allows for a clear association between a MPxTransform and a
	MPxTransformationMatrix.

	When registering the MPxTransformationMatrix, a MTypeId is required.
	For nodes using the default MPxTransformationMatrix, a statically
	defined MTypeId is provided by the
	MPxTransformationMatrix::baseTransformationMatrixId data member.

	Since the MPxTransformationMatrix class gives extended functionality
	to a native Maya class, several methods are given that are needed
	by Maya for this class to properly function in different settings.

	To create a transformation matrix, derive from this class and overload
	the creator() method and the assignment operator for the derived class.
	If any additional data items are added to this class, the copyValues()
	method should also be overloaded. This will ensure that the new values
	will get properly handed by Maya. The rest of the methods may be
	overloaded as needed.
*/
class OPENMAYA_EXPORT MPxTransformationMatrix {
public:
					MPxTransformationMatrix();
					MPxTransformationMatrix(const MTransformationMatrix &);
					MPxTransformationMatrix(const MPxTransformationMatrix &);
					MPxTransformationMatrix(const MMatrix &);
	virtual			~MPxTransformationMatrix();

	virtual void	copyValues(MPxTransformationMatrix *);

	virtual 		MTypeId	typeId() const;

	MPxTransformationMatrix & operator = (const MPxTransformationMatrix &src);
	MPxTransformationMatrix & operator = (const MMatrix &src);
	MPxTransformationMatrix & operator = (const MTransformationMatrix &src);
	bool	  				  operator == (const MPxTransformationMatrix &);
	bool	  				  operator != (const MPxTransformationMatrix &);
	bool					  operator == (const MTransformationMatrix &);
	bool	  				  operator != (const MTransformationMatrix &);
	bool					  operator == (const MMatrix &);
	bool					  operator != (const MMatrix &);

	virtual bool 				isEquivalent(const MPxTransformationMatrix &,
										double tolerance = MMatrix_kTol) const;
	virtual bool 				isEquivalent(const MTransformationMatrix &,
										double tolerance = MMatrix_kTol) const;
	virtual bool 				isEquivalent(const MMatrix &,
										double tolerance = MMatrix_kTol) const;
	virtual MPxTransformationMatrix reverse() const;
	virtual MPxTransformationMatrix	&transformBy(const MTransformationMatrix &);

	virtual MMatrix		asMatrix() const;
	virtual MMatrix		asMatrixInverse() const;
	virtual MMatrix		asScaleMatrix() const;
	virtual MMatrix 	asScaleMatrixInverse() const;
	virtual MMatrix		asRotateMatrix() const;
	virtual MMatrix 	asRotateMatrixInverse() const;
	virtual MMatrix		asMatrix(double percent) const;
	virtual MMatrix		asInterpolationMatrix(const MTransformationMatrix &toM,
											double percent, bool rot,
											int direction = 0) const;
	virtual MTransformationMatrix	asTransformationMatrix() const;

	//
	//	Translation methods:
	//

	virtual MVector 		translation(MSpace::Space = MSpace::kTransform,
										MStatus* ReturnStatus = NULL) const;
	virtual MStatus 		translateTo(const MVector &vector,
										MSpace::Space = MSpace::kTransform);
	virtual MStatus			translateBy(const MVector &vector,
										MSpace::Space = MSpace::kTransform);

	//
	//	Rotation methods:
	//

	virtual MQuaternion		rotation(MSpace::Space = MSpace::kTransform,
									 MStatus *ReturnStatus = NULL) const;
	virtual MEulerRotation	eulerRotation(MSpace::Space space = MSpace::kTransform,
									MStatus *ReturnStatus = NULL) const;
	virtual MStatus 	rotateTo(const MQuaternion &q,
								 MSpace::Space = MSpace::kTransform);
	virtual MStatus 	rotateBy(const MQuaternion &q,
								 MSpace::Space = MSpace::kTransform);
	virtual MStatus		rotateTo(const MEulerRotation &e,
								 MSpace::Space = MSpace::kTransform);
	virtual MStatus 	rotateBy(const MEulerRotation &e,
								 MSpace::Space = MSpace::kTransform);
	virtual MTransformationMatrix::RotationOrder
						rotationOrder(MStatus* ReturnStatus = NULL) const;
	virtual MStatus		setRotationOrder(MTransformationMatrix::RotationOrder,
										 bool preserve = true);
	virtual MQuaternion	rotateOrientation(MSpace::Space = MSpace::kTransform,
											MStatus* ReturnStatus = NULL) const;
	virtual MStatus 	setRotateOrientation(const MQuaternion &q,
											MSpace::Space = MSpace::kTransform,
											bool balance = true);
	virtual MEulerRotation	eulerRotateOrientation(MSpace::Space = MSpace::kTransform,
											MStatus* ReturnStatus = NULL) const;
	virtual MStatus 	setRotateOrientation(const MEulerRotation &euler,
											MSpace::Space = MSpace::kTransform,
											bool balance = true);

	//
	//	Scale methods:
	//

	virtual MVector		scale(MSpace::Space = MSpace::kTransform,
								MStatus* ReturnStatus = NULL) const;
	virtual MStatus		scaleTo(const MVector &,
								MSpace::Space = MSpace::kTransform);
	virtual MStatus 	scaleBy(const MVector &,
								MSpace::Space = MSpace::kTransform);

	//	Shear methods:
	//
	virtual MVector	shear(MSpace::Space = MSpace::kTransform,
							MStatus* ReturnStatus = NULL) const;
	virtual MStatus	shearTo(const MVector& shear,
							MSpace::Space = MSpace::kTransform);
	virtual MStatus	shearBy(const MVector& shear,
							MSpace::Space = MSpace::kTransform);

	//	Scale pivot methods:
	//
	virtual MPoint	scalePivot(MSpace::Space = MSpace::kTransform,
								MStatus* ReturnStatus = NULL) const;
	virtual MStatus setScalePivot(const MPoint &,
									MSpace::Space = MSpace::kTransform,
									bool balance = true);
	virtual MVector	scalePivotTranslation(MSpace::Space = MSpace::kTransform,
										MStatus* ReturnStatus = NULL) const;
	virtual MStatus	setScalePivotTranslation(const MVector &vector,
										MSpace::Space = MSpace::kTransform);

	//	Rotate pivot methods:

	virtual MPoint	rotatePivot(MSpace::Space = MSpace::kTransform,
								MStatus* ReturnStatus = NULL) const;
	virtual MStatus setRotatePivot(const MPoint &,
									MSpace::Space = MSpace::kTransform,
									bool balance = true);
	virtual MVector	rotatePivotTranslation(MSpace::Space = MSpace::kTransform,
											MStatus* ReturnStatus = NULL) const;
	virtual MStatus	setRotatePivotTranslation(const MVector &vector,
										MSpace::Space = MSpace::kTransform);
	virtual	MStatus unSquishIt();
	virtual MMatrix unSquishMatrix() const;

	static MPxTransformationMatrix *creator();

	static MEulerRotation::RotationOrder
			convertTransformationRotationOrder(MTransformationMatrix::RotationOrder,
								 MStatus *ReturnStatus = NULL);
	static MTransformationMatrix::RotationOrder
					convertEulerRotationOrder(MEulerRotation::RotationOrder,
										 MStatus *ReturnStatus = NULL);

	//! The identity transformation matrix.
	static const  MPxTransformationMatrix identity;

	//! Type id for the default MPxTransformationMatrix.
	static MTypeId		baseTransformationMatrixId;

BEGIN_NO_SCRIPT_SUPPORT:

	// Obsolete & no script support
	static MEulerRotation::RotationOrder
			convertRotationOrder(MTransformationMatrix::RotationOrder,
								 MStatus *ReturnStatus = NULL);
	// Obsolete & no script support
	static MTransformationMatrix::RotationOrder
					convertRotationOrder(MEulerRotation::RotationOrder,
										 MStatus *ReturnStatus = NULL);

	//	No script support
	friend std::ostream &operator << (std::ostream &os, const MPxTransformationMatrix &m);

END_NO_SCRIPT_SUPPORT:

protected:
	virtual	MStatus		decomposeMatrix(const MMatrix &);

	//!	Scale component of transformation.
	MVector				scaleValue;

	//! Rotation component of transformation.
	MEulerRotation		rotationValue;

	//! Translation component of transformation.
	MVector				translationValue;

	//! Shear component of transformation.
	MVector				shearValue;

	//! Position of pivot used for scaling.
	MPoint 				scalePivotValue;

	//! Translation to compensate for movement of the scale pivot.
	MVector				scalePivotTranslationValue;

	//! Position of pivot used for rotation.
	MPoint				rotatePivotValue;

	//! Translation to compensate for movement of the rotate pivot.
	MVector 			rotatePivotTranslationValue;

	//! Orientation of the local rotation space.
	MQuaternion			rotateOrientationValue;

	static const char*	className();

private:
	void*				instance;

};

#endif /* __cplusplus */
#endif /* _MPxTransformationMatrix */
